home *** CD-ROM | disk | FTP | other *** search
- #include <string.h>
- #include <stdlib.h>
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <linux/ip.h>
- #include <linux/tcp.h>
- #include <linux/udp.h>
- #include <linux/icmp.h>
- #include <linux/if.h>
- #include <linux/ip_fw.h>
- #include <limits.h>
- #include <netdb.h>
- #include "netconf.h"
- #include "internal.h"
- #include "firewall.h"
- #include "../dialog/dialog.h"
- #include "../misc/misc.h"
- #include "../userconf/userconf.h"
- #include "../paths.h"
- #include "netconf.m"
-
- #ifndef IP_FW_POLICY_IN
- /* These are just here so it compiles */
- #define IP_FW_F_MASQ 0
- #define IP_FW_APPEND_OUT 1
- #define IP_FW_APPEND_IN 2
- #define IP_FW_APPEND_FWD 3
-
- #define FIREWAALL_NONE
- #endif
-
- NETCONF_HELP_FILE help_ipfw ("firewall");
-
-
- PROTECTED IPFW_RULE::IPFW_RULE()
- {
- from.interface.setfrom ("Any");
- to.interface.setfrom ("Any");
- protocol.setfrom ("all");
- /* #Specification: netconf / firewalling / active rule
- One rule may be defined and desactivated without erasing it.
- This give some flexibility to the administrator to define
- complex rules and "comment out" some.
- */
- active = 1;
- }
- /*
- Extract a number from a buffer.
- The number may be enclosed in double quote.
- */
- static const char *firewall_extract (const char *buf, char &val)
- {
- SSTRING s;
- buf = str_extract (buf,s);
- val = s.getval();
- return buf;
- }
-
- static const char *firewall_extract (const char *buf, IPFW_SRC &s)
- {
- buf = str_extract (buf,s.host);
- buf = str_extract (buf,s.netmask);
- buf = str_extract (buf,s.portrange);
- buf = str_extract (buf,s.ports);
- buf = str_extract (buf,s.interface);
- return buf;
- }
-
- PROTECTED IPFW_RULE::IPFW_RULE(const char * &buf)
- {
- buf = firewall_extract (buf,active);
- buf = str_extract (buf,protocol);
- buf = firewall_extract (buf,from);
- buf = firewall_extract (buf,to);
- }
-
- PUBLIC IPFW_RULE_FORWARD::IPFW_RULE_FORWARD(const char *buf)
- : IPFW_RULE (buf)
- {
- firewall_extract (buf,masquerade);
- }
- PUBLIC IPFW_RULE_FORWARD::IPFW_RULE_FORWARD()
- {
- masquerade = 0;
- }
-
- PUBLIC IPFW_RULE_OUTPUT::IPFW_RULE_OUTPUT(const char *buf)
- : IPFW_RULE (buf)
- {
- }
- PUBLIC IPFW_RULE_OUTPUT::IPFW_RULE_OUTPUT()
- {
- }
-
- PUBLIC IPFW_RULE_INPUT::IPFW_RULE_INPUT(const char *buf)
- : IPFW_RULE (buf)
- {
- }
- PUBLIC IPFW_RULE_INPUT::IPFW_RULE_INPUT()
- {
- }
-
- static void firewall_append (char *buf, SSTRING &s)
- {
- strcat (buf," \"");
- strcat (buf,s.get());
- strcat (buf,"\"");
- }
-
- static void firewall_append (char *buf, int val)
- {
- char valstr[20];
- sprintf (valstr,"%d",val);
- strcat (buf," \"");
- strcat (buf,valstr);
- strcat (buf,"\"");
- }
-
- static void firewall_append (char *buf, IPFW_SRC &s)
- {
- firewall_append (buf,s.host);
- firewall_append (buf,s.netmask);
- firewall_append (buf,s.portrange);
- firewall_append (buf,s.ports);
- firewall_append (buf,s.interface);
- }
-
- char FIREWALL[] = "firewall";
- char FORWARD[] = "forward";
- char BLOCK[] = "block";
- char OUTPUT[] = "output";
-
- /*
- Save one forward line in /etc/conf.linuxconf
- */
- PROTECTED void IPFW_RULE::savek(char *buf)
- {
- buf[0] = '\0';
- firewall_append (buf,active);
- firewall_append (buf,protocol);
- firewall_append (buf,from);
- firewall_append (buf,to);
- }
-
- /*
- Save one forward line in /etc/conf.linuxconf
- */
- PUBLIC void IPFW_RULE_FORWARD::save()
- {
- char buf[2000];
- IPFW_RULE::savek(buf);
- firewall_append (buf,masquerade);
- linuxconf_add (FIREWALL,FORWARD,buf);
- }
- /*
- Save one forward line in /etc/conf.linuxconf
- */
- PUBLIC void IPFW_RULE_INPUT::save()
- {
- char buf[2000];
- IPFW_RULE::savek(buf);
- linuxconf_add (FIREWALL,BLOCK,buf);
- }
- /*
- Save one output line in /etc/conf.linuxconf
- */
- PUBLIC void IPFW_RULE_OUTPUT::save()
- {
- char buf[2000];
- IPFW_RULE::savek(buf);
- linuxconf_add (FIREWALL,OUTPUT,buf);
- }
-
- /*
- Format the minimum information about the rule so it will
- be presentable in a menu.
- */
- PUBLIC void IPFW_RULE::present (char *buf)
- {
- sprintf (buf,"[%c] %-4s %4s:%-10s <-> %4s:%-10s"
- ,active ? 'X' : ' '
- ,protocol.get()
- ,from.interface.get()
- ,from.host.get()
- ,to.interface.get()
- ,to.host.get());
- }
-
- static void ipfwrule_computemsk (const char ip[], char msk[])
- {
- int num4[4];
- device_aip24 (ip,num4);
- if (num4[3] != 0){
- strcpy (msk,"255.255.255.255");
- }else{
- char std_net[20];
- device_setstdnetmask(ip,std_net,msk);
- }
- }
- /*
- try to convert something into an IP number
- Return -1 if it can't.
- */
- int ipfwrule_convert (
- const char *str, // An IP number, a host name or an interface
- // name (eth0)
- char ip[],
- char msk[]) // Corresponding (computed) netmask
- // or extracted from the device
- {
- int ret = 0;
- struct hostent *hent;
- struct netent *nent;
- IFCONFIG_INFO info;
- if (device_validip(str,false)){
- strcpy (ip,str);
- ipfwrule_computemsk (str,msk);
- }else if (ifconfig_getinfo(str,info)!=-1){
- // This is a network devices and we must
- // pick the IP number since ipfw don't do it.
- strcpy (ip,info.ip_addr);
- strcpy (msk,info.netmask);
- }else if ((hent = gethostbyname(str)) != NULL){
- devices_ip2a (hent,ip);
- ipfwrule_computemsk (ip,msk);
- }else if ((nent = getnetbyname(str)) != NULL){
- devices_ip2a (nent,ip);
- ipfwrule_computemsk (ip,msk);
- }else{
- ret = -1;
- }
- return ret;
- }
-
- /*
- try to convert something into an IP number
- Return -1 if it can't.
- */
- static int ipfwrule_convert (
- const char *str, // An IP number, a host name or an interface
- // name (eth0)
- char ip[])
- {
- char msk[16];
- return ipfwrule_convert (str,ip,msk);
- }
- /*
- Return the number of significative bits in the netmask (1's)
-
- Return -1 if any error.
- */
- PUBLIC int IPFW_RULE::nbbitmask(IPFW_SRC &f)
- {
- int ret = f.nbbit_msk;
- if (ret == -1){
- const char *msk = f.netmask.get();
- char std_msk[20];
- if (*msk == '\0'){
- /* #Specification: firewall / netmask
- The netmask is optionnal. It is automacly
- compute from the host/network number
- */
- char ip[20];
- if (ipfwrule_convert(f.host.get(),ip,std_msk)!=-1){
- msk = std_msk;
- }else{
- ret = -1;
- }
- }
- int num4[4];
- device_aip24 (msk,num4);
- unsigned long nmsk = (num4[0] << 24) | (num4[1] << 16)
- | (num4[2] << 8) | num4[3];
- unsigned long cmp = 0x80000000l;
- int i;
- for (i=0; i<32 && (nmsk & cmp) != 0; i++, cmp >>= 1);
- ret = i;
- f.nbbit_msk = ret;
- }
- return ret;
- }
-
- /*
- Return the number of significative bits in the netmask (1's)
-
- This is taken in the from.
- */
- PUBLIC int IPFW_RULE::nbbitmask_from()
- {
- return nbbitmask (from);
- }
- /*
- Return the number of significative bits in the netmask (1's)
-
- This is taken in the "to".
- */
- PUBLIC int IPFW_RULE::nbbitmask_to()
- {
- return nbbitmask (to);
- }
- /*
- Return -1 if abort
- Return 0 if accept
- Return 1 if delete required
- */
- PUBLIC int IPFW_RULE::editk(
- DIALOG &dia,
- const char *title)
- {
- dia.newf_chk ("",active,MSG_U(F_RULEACTIVE,"This rule is active"));
- int i;
- FIELD_COMBO *comb = dia.newf_combo (MSG_U(F_PROTOCOL,"Protocol")
- ,protocol);
- for (i=0; i<4; i++){
- static const char *tbproto[]={
- "icmp","udp","tcp","all"
- };
- comb->addopt (tbproto[i]);
- }
-
- static const char *tbinter[][2]={
- {"Any", MSG_U(F_PACKFROMANY,"Packet come from anywhere") },
- {"eth0", MSG_U(F_FIRSTETH,"First ethernet adaptor")},
- {"eth1", MSG_U(F_SECOND,"Second")},
- {"eth2", MSG_U(F_THIRD,"Third")},
- {"eth3", MSG_U(F_FOURTH,"Fourth")},
- {"sl0", MSG_U(F_FIRSTSLIP,"First SLIP/CSLIP channel")},
- {"sl1", MSG_R(F_SECOND)},
- {"ppp0", MSG_U(F_FIRSTPPP,"First PPP channel")},
- {"ppp1", MSG_R(F_SECOND)},
- };
-
- dia.newf_title ("",MSG_U(F_FROM,"From"));
- dia.newf_str (MSG_U(F_HOSTORNET,"Host or Network"),from.host);
- dia.newf_str (MSG_U(F_HNETMASK,"Netmask"),from.netmask);
- dia.newf_str (MSG_U(F_PORTRANGE,"Port range"),from.portrange);
- dia.newf_str (MSG_U(F_OTHERPORTS,"Other ports"),from.ports);
- comb = dia.newf_combo (MSG_U(F_INTERFACE,"Interface"),from.interface);
- for (i=0; i<9; i++){
- comb->addopt (tbinter[i][0],tbinter[i][1]);
- }
-
- dia.newf_title ("",MSG_U(F_TO,"To"));
- dia.newf_str (MSG_R(F_HOSTORNET),to.host);
- dia.newf_str (MSG_R(F_HNETMASK),to.netmask);
- dia.newf_str (MSG_R(F_PORTRANGE),to.portrange);
- dia.newf_str (MSG_R(F_OTHERPORTS),to.ports);
-
- comb = dia.newf_combo (MSG_R(F_INTERFACE),to.interface);
- for (i=0; i<9; i++){
- comb->addopt (tbinter[i][0],tbinter[i][1]);
- }
- int ret = -1;
- int nof = 0;
- while (1){
- MENU_STATUS code = dia.edit (title
- ,""
- ,help_ipfw.getpath()
- ,nof
- ,MENUBUT_CANCEL|MENUBUT_ACCEPT|MENUBUT_DEL);
- if (code == MENU_ESCAPE || code == MENU_CANCEL){
- break;
- }else if (code == MENU_DEL){
- ret = 1;
- break;
- }else{
- ret = 0;
- break;
- }
- }
- if (ret != 0) dia.restore();
- return ret;
- }
-
- /*
- Return -1 if abort
- */
- PUBLIC int IPFW_RULE_FORWARD::edit()
- {
- DIALOG dia;
- dia.newf_chk ("",masquerade,MSG_U(F_DOMASQUERADE,"Do masquerading"));
- return IPFW_RULE::editk (dia,MSG_U(T_FORWARDING,"Firewall forwarding rule"));
- }
- /*
- Return -1 if abort
- */
- PUBLIC int IPFW_RULE_OUTPUT::edit()
- {
- DIALOG dia;
- return IPFW_RULE::editk (dia,MSG_U(T_OUTPUT,"Firewall Outputing rule"));
- }
- /*
- Return -1 if abort
- */
- PUBLIC int IPFW_RULE_INPUT::edit()
- {
- DIALOG dia;
- return IPFW_RULE::editk (dia,MSG_U(T_INPUTING,"Firewall inputing rule"));
- }
-
- PUBLIC int IPFW_RULE::setup(
- IPFW_SRC &f,
- IPFW_SRC &t,
- const char *type,
- int doit, // Exec the command ?
- SSTRING *collect) // Will contain a copy of the
- // command generated
- {
- int ret = 0;
- if (active){
- char interbuf[100];
- strcpy (interbuf,"0.0.0.0");
- if (!f.interface.is_empty()
- && f.interface.cmp("Any")!=0){
- /* #Specification: firewall / iface argument
- We accept a host name, an IP number or
- a network device name (eth0).
- */
- char ip[20];
- const char *ifacearg = f.interface.get();
- if (ipfwrule_convert (ifacearg,ip)!=-1){
- sprintf (interbuf,"%s",ip);
- }else{
- xconf_error (MSG_U(E_IVLDINTER
- ,"Invalid interface %s for firewalling rule")
- ,ifacearg);
- ret = -1;
- }
- }
- /* #Specification: firewall / forwarding / accept
- The firewalling interface support only accepting rule
- so far. It is expect to be enough for most firewalls.
-
- Supporting denying and rejecting is not much of a problem
- although, Experience will shows us how to do this
- without confusing the user...
-
- Comments are welcome.
- */
- char fhoststr[PATH_MAX],fhostmsk[16];
- ret |= ipfwrule_convert (f.host.get(),fhoststr,fhostmsk);
- char thoststr[PATH_MAX],thostmsk[16];
- ret |= ipfwrule_convert (t.host.get(),thoststr,thostmsk);
- struct ip_fw bf;
- if (ipfw_baseinit(interbuf,protocol.get()
- ,fhoststr,f.netmask.is_empty() ? fhostmsk : f.netmask.get()
- ,f.portrange.get(),f.ports.get()
- ,thoststr,t.netmask.is_empty() ? thostmsk : t.netmask.get()
- ,t.portrange.get(),t.ports.get()
- ,bf)!=-1){
- int command = 0;
- if (type[0] == 'm'){
- command = IP_FW_APPEND_FWD;
- bf.fw_flg |= IP_FW_F_MASQ;
- }else if (type[0] == 'f'){
- command = IP_FW_APPEND_FWD;
- }else if (type[0] == 'o'){
- command = IP_FW_APPEND_OUT;
- }else if (type[0] == 'b'){
- command = IP_FW_APPEND_IN;
- }
- ret = ipfw_append (doit,collect,command,bf);
- }else{
- ret = -1;
- }
- }
- return ret;
- }
-
- /*
- Setup one side of the forwarding rule (from -> to)
- */
- PUBLIC int IPFW_RULE_FORWARD::setup_left(int doit, SSTRING *collect)
- {
- int ret = -1;
- if (masquerade){
- ret = setup (from,to,"m",doit,collect);
- }else{
- ret = setup (from,to,"f",doit,collect);
- }
- return ret;
- }
- /*
- Setup one side of the forwarding rule (to -> from)
- */
- PUBLIC int IPFW_RULE_FORWARD::setup_right(int doit, SSTRING *collect)
- {
- int ret = 0;
- if (!masquerade){
- ret = setup (to,from,"f",doit,collect);
- }
- return ret;
- }
- /*
- Setup one side of the forwarding rule (from -> to)
- */
- PUBLIC int IPFW_RULE_OUTPUT::setup_left(int doit, SSTRING *collect)
- {
- return setup (from,to,"o",doit,collect);
- }
- /*
- Setup one side of the forwarding rule (to -> from)
- */
- PUBLIC int IPFW_RULE_OUTPUT::setup_right(int doit, SSTRING *collect)
- {
- return setup (to,from,"o",doit,collect);
- }
-
-
- /*
- Setup one side of the blocking rule (from -> to)
- */
- PUBLIC int IPFW_RULE_INPUT::setup_left(int doit, SSTRING *collect)
- {
- return setup (from,to,"b",doit,collect);
- }
- /*
- Setup one side of the blocking rule (to -> from)
- */
- PUBLIC int IPFW_RULE_INPUT::setup_right(int doit, SSTRING *collect)
- {
- return setup (to,from,"b",doit,collect);
- }
-
-
-